package com.shermanzhou.codegen;

import com.shermanzhou.codegen.core.CodeGeneratorTool;
import com.shermanzhou.codegen.core.model.ClassInfo;
import com.shermanzhou.codegen.util.FreemarkerTool;
import com.shermanzhou.codegen.util.FreemarkerUtil;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhouchaoqun
 * @date 2018/12/12 上午11:34
 */
public class Generator {

    private FreemarkerTool freemarkerTool;

    public static void main(String[] args) {

        String tableSQl = "CREATE TABLE `zeus_user` (\n" +
                "  `id` bigint(20) NOT NULL COMMENT '用户表，全局唯一ID，由服务生成',\n" +
                "  `login_id` varchar(32) DEFAULT NULL COMMENT '用户登录名',\n" +
                "  `nick_name` varchar(32) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '用户昵称',\n" +
                "  `mobile` varchar(32) DEFAULT NULL COMMENT '登录手机',\n" +
                "  `email` varchar(255) DEFAULT NULL COMMENT '登录邮箱',\n" +
                "  `platform_type` varchar(32) DEFAULT NULL COMMENT '平台类型：商宴通、费控、会务等',\n" +
                "  `pwd` varchar(255) DEFAULT NULL COMMENT '密码Hash',\n" +
                "  `pwd_expire` datetime DEFAULT NULL COMMENT '密码过期时间',\n" +
                "  `pwd_salt` varchar(32) DEFAULT NULL COMMENT '密码Salt',\n" +
                "  `pwd_encryption` varchar(32) DEFAULT NULL COMMENT '密码加密方式',\n" +
                "  `reg_time` datetime DEFAULT NULL COMMENT '注册时间',\n" +
                "  `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像URL',\n" +
                "  `status` varchar(32) DEFAULT NULL COMMENT '状态：ACTIVE--启用, DISABLED--禁用, INACTIVE--未激活, UNVERIFIED--未认证, UNREGISTERED--未注册',\n" +
                "  `weixin_openid` varchar(128) DEFAULT NULL COMMENT '微信Bind，openid',\n" +
                "  `dingding_openid` varchar(128) DEFAULT NULL COMMENT '钉钉bind，dingdingcode',\n" +
                "  `weibo_openid` varchar(128) DEFAULT NULL COMMENT '微博bind，openid',\n" +
                "  `google_openid` varchar(128) DEFAULT NULL COMMENT 'google oauth bind, oauth token',\n" +
                "  `facebook_openid` varchar(128) DEFAULT NULL COMMENT 'facebook oauth bind, oauth token',\n" +
                "  `twitter_openid` varchar(128) DEFAULT NULL COMMENT 'twitter oauth bind, twitter oauth token',\n" +
                "  `oauth_openid1` varchar(128) DEFAULT NULL COMMENT 'oauth bind token',\n" +
                "  `oauth_openid2` varchar(128) DEFAULT NULL COMMENT 'oauth bind token',\n" +
                "  `oauth_openid3` varchar(128) DEFAULT NULL COMMENT 'oauth bind token',\n" +
                "  `oauth_openid4` varchar(128) DEFAULT NULL COMMENT 'oauth bind token',\n" +
                "  `custom1` varchar(255) DEFAULT NULL COMMENT '预留字段',\n" +
                "  `custom2` varchar(255) DEFAULT NULL COMMENT '预留字段',\n" +
                "  `custom3` varchar(255) DEFAULT NULL COMMENT '预留字段',\n" +
                "  `custom4` varchar(255) DEFAULT NULL COMMENT '预留字段',\n" +
                "  `gmt_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间，创建时自动添加',\n" +
                "  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间，更新时自动更新',\n" +
                "  `gmt_activated` datetime DEFAULT NULL COMMENT '记录激活时间',\n" +
                "  PRIMARY KEY (`id`),\n" +
                "  UNIQUE KEY `idx_mobile` (`mobile`),\n" +
                "  UNIQUE KEY `idx_email` (`email`),\n" +
                "  UNIQUE KEY `idx_login_id` (`login_id`)\n" +
                ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='zeus用户中心，用户表';";

        Generator generator = new Generator();
        generator.freemarkerTool = new FreemarkerTool(FreemarkerUtil.freemarkerConfig);
        Map<String, String> codeMap = generator.codeGenerate(tableSQl);
        for (Map.Entry<String, String> entry : codeMap.entrySet()) {
            Writer out = null;
            try {
                String filePath = entry.getKey();
                String fileContent = entry.getValue();
                String outFullPath = "code-generator/src/main/java/" + filePath;
                File file = new File(outFullPath);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                out = new FileWriter(file);
                out.write(fileContent);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 代码生成
     * @param tableSql
     * @return map<filePath, code>
     */
    public Map<String, String> codeGenerate(String tableSql) {
        try {
            if (StringUtils.isBlank(tableSql)) {
                return null;
            }

            // parse table
            ClassInfo classInfo = CodeGeneratorTool.processTableIntoClassInfo(tableSql);

            classInfo.setBasePackage("com.quancheng.zeus");
            classInfo.setAppName("zeus");

            String filePrefix = classInfo.getBasePackage().replace('.', '/') + "/";

            // code genarete
            Map<String, Object> params = new HashMap<>();
            params.put("classInfo", classInfo);

            // result
            Map<String, String> result = new HashMap<>();

            result.put(filePrefix + "controller/" + classInfo.getClassName() + "Controller.java", freemarkerTool.processString("controller.ftl", params));
            result.put(filePrefix + "service/" + classInfo.getClassName() + "Service.java", freemarkerTool.processString("service.ftl", params));
            result.put(filePrefix + "service/impl/" + classInfo.getClassName() + "ServiceImpl.java", freemarkerTool.processString("service_impl.ftl", params));

            result.put(filePrefix + "dao/" + classInfo.getClassName() + "Mapper.java", freemarkerTool.processString("mapper.ftl", params));
            result.put(filePrefix + "xml/" + classInfo.getClassName() + "Mapper.xml", freemarkerTool.processString("mybatis.ftl", params));
            result.put(filePrefix + "dataobject/" + classInfo.getClassName() + "DO.java", freemarkerTool.processString("model.ftl", params));

            String protoPathPrefix = "proto/" + classInfo.getAppName() + "/" + classInfo.getClassName().replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
            result.put(protoPathPrefix + ".proto", freemarkerTool.processString("message_proto.ftl", params));
            result.put(protoPathPrefix + "_service.proto", freemarkerTool.processString("service_proto.ftl", params));

            // 计算,生成代码行数
            int lineNum = 0;
            for (Map.Entry<String, String> item: result.entrySet()) {
                if (item.getValue() != null) {
                    lineNum += StringUtils.countMatches(item.getValue(), "\n");
                }
            }
            return result;

        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
        return null;
    }
}
